﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Drawing;
using System.Web.UI.WebControls;
using System.Collections.Specialized;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace Exaction.UI.UserControls
{
    public class LinkedListBoxes : UserControl, INamingContainer
    {
        #region "Members"
        protected LiteralControl LtMoveItemToRightJS;
        protected LiteralControl LtMoveItemToLeftJS;
        protected HiddenField HfSelectedItems;

        private ListBox _sourceListBox;
        private ListBox _destinationListBox;

        #endregion

        #region "Properties"
        /// <summary>
        /// Gets or sets the main list box.
        /// </summary>
        /// <value>The main list box.</value>
        public ListBox SourceListBox
        {
            get { return _sourceListBox; }            
        }
        public List<ListItem> SelectedItems { get; set; }
        #endregion

        #region "Constructor"
        public LinkedListBoxes()
        {
            _sourceListBox = new ListBox();
            HfSelectedItems = new HiddenField();
            _destinationListBox = new ListBox();
            LtMoveItemToLeftJS = new LiteralControl();
            LtMoveItemToRightJS = new LiteralControl();
            SelectedItems = new List<ListItem>();
        }
        #endregion

        #region "Events"
        /// <summary>
        /// Raises the <see cref="E:System.Web.UI.Control.Init"/> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs"/> object that contains the event data.</param>
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            EnsureChildControls();
        }
        /// <summary>
        /// Called by the ASP.NET page framework to notify server controls that use composition-based implementation to create any child controls they contain in preparation for posting back or rendering.
        /// </summary>
        protected override void CreateChildControls()
        {
            _sourceListBox.Width = new Unit(150, UnitType.Pixel);
            _sourceListBox.Rows = 10;
            _sourceListBox.SelectionMode = ListSelectionMode.Multiple;
            _sourceListBox.EnableViewState = false;
            _sourceListBox.ID = this.ID + "_mainListBox";

            _destinationListBox.Width = new Unit(150, UnitType.Pixel);
            _destinationListBox.Rows = 10;
            _destinationListBox.EnableViewState = false;
            _destinationListBox.SelectionMode = ListSelectionMode.Multiple;
            _destinationListBox.ID = this.ID + "_selectionListBox";

            this.Controls.Add(_sourceListBox);
            this.Controls.Add(_destinationListBox);
            this.Controls.Add(HfSelectedItems);
            this.Controls.Add(LtMoveItemToLeftJS);
            this.Controls.Add(LtMoveItemToRightJS);

            LtMoveItemToLeftJS.Text = "<input onclick=\"Javascript:RemoveItem('" + _destinationListBox.ClientID + "', '" + _sourceListBox.ClientID + "', '" + HfSelectedItems.ClientID + "');\" type=button value='< Remove' />";
            LtMoveItemToRightJS.Text = "<input onclick=\"Javascript:AddItem('" + _sourceListBox.ClientID + "', '" + _destinationListBox.ClientID + "','" + HfSelectedItems.ClientID + "');\" type=button value='   Add >   ' />";

            string js = "function AddItem(ctrlSource, ctrlTarget, hiddenField) {var Source = document.getElementById(ctrlSource);var Target = document.getElementById(ctrlTarget);var HiddenFieldValue = document.getElementById(hiddenField);if ((Source != null) && (Target != null)) {while ( Source.options.selectedIndex >= 0 ) {var newOption = new Option(); newOption.text = Source.options[Source.options.selectedIndex].text;newOption.value = Source.options[Source.options.selectedIndex].value;Target.options[Target.length] = newOption; Source.remove(Source.options.selectedIndex); HiddenFieldValue.value = HiddenFieldValue.value + newOption.value + '#;';} }} function RemoveItem(ctrlSource, ctrlTarget, hiddenField) {var Source = document.getElementById(ctrlSource);var Target = document.getElementById(ctrlTarget);var HiddenFieldValue = document.getElementById(hiddenField);if ((Source != null) && (Target != null)) { while (Source.options.selectedIndex >= 0) {var newOption = new Option();  newOption.text = Source.options[Source.options.selectedIndex].text; newOption.value = Source.options[Source.options.selectedIndex].value;Target.options[Target.length] = newOption; Source.remove(Source.options.selectedIndex);HiddenFieldValue.value = HiddenFieldValue.value.replace(newOption.value + '#;', '');}}}";
            this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "linkedlistboxes", js, true);

        }
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            SetSelectedItems();
        }
        /// <summary>
        /// Sends server control content to a provided <see cref="T:System.Web.UI.HtmlTextWriter"/> object, which writes the content to be rendered on the client.
        /// </summary>
        /// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the server control content.</param>
        protected override void Render(HtmlTextWriter writer)
        {

            writer.RenderBeginTag(HtmlTextWriterTag.Table);
            writer.RenderBeginTag(HtmlTextWriterTag.Tr);

            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            _sourceListBox.RenderControl(writer);
            writer.RenderEndTag();

            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.Write("&nbsp;");
            writer.RenderEndTag();

            writer.RenderBeginTag(HtmlTextWriterTag.Td);

            writer.RenderBeginTag(HtmlTextWriterTag.Center);

            writer.RenderBeginTag(HtmlTextWriterTag.P);
            LtMoveItemToRightJS.RenderControl(writer);
            writer.RenderEndTag();

            writer.RenderBeginTag(HtmlTextWriterTag.P);
            LtMoveItemToLeftJS.RenderControl(writer);
            writer.RenderEndTag();

            writer.RenderEndTag();

            writer.RenderEndTag();

            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.Write("&nbsp;");
            writer.RenderEndTag();

            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            _destinationListBox.RenderControl(writer);
            writer.RenderEndTag();

            writer.RenderEndTag();

            writer.RenderEndTag();

            HfSelectedItems.RenderControl(writer);
        }
        #endregion

        #region "Methods"
        /// <summary>
        /// Gets the selected values.
        /// </summary>
        /// <returns></returns>
        private void SetSelectedItems()
        {
            StringBuilder sbSelectedValues = new StringBuilder();
            _destinationListBox.Items.Clear();
            if (!IsPostBack)
            {
                foreach (ListItem item in SourceListBox.Items)
                {
                    if (item.Selected)
                    {
                        sbSelectedValues.Append(item.Value + "#;");
                        item.Selected = false;
                    }
                }
                HfSelectedItems.Value = sbSelectedValues.ToString();
            }            
            
            String[] selectedValues = HfSelectedItems.Value.Split(new string[] { "#;" }, StringSplitOptions.RemoveEmptyEntries);
            ListItem selectedItem;

            foreach (string item in selectedValues)
            {
                selectedItem = SourceListBox.Items.FindByValue(item);

                SourceListBox.Items.Remove(selectedItem);
                _destinationListBox.Items.Add(selectedItem);
                if (IsPostBack)
                {
                    sbSelectedValues.Append(item + "#;");
                }
                SelectedItems.Add(selectedItem);

            }
            HfSelectedItems.Value = sbSelectedValues.ToString();            
        }

        #endregion
    }
}
